#![allow(dead_code)]

use crate::config::EntryPoint;
use anyhow::Error;
use serde_json::to_string;
use std::fmt::{Display, Formatter};
use wd_macro::ChainSet;
use wd_run::Context;

macro_rules! new_control_event {
    ($name:tt,$enum:tt) => {
        pub fn $name() -> Self {
            let kind = EventKind::$enum;
            Self::default().set_kind(kind)
        }
    };
    ($name:tt,$type:ty,$enum:tt) => {
        pub fn $name(kind: $type) -> Self {
            let kind = EventKind::$enum(kind);
            Self::default().set_kind(kind)
        }
    };
}

pub struct ControlEvent {
    pub kind: EventKind,
    pub context: Context,
    pub opt: Operation,
}
impl ControlEvent {
    new_control_event!(new_build_ep, EntryPoint, BuildEP);
    new_control_event!(new_remove_ep, String, RemoveEP);
    new_control_event!(new_operation, String, Operation);
    new_control_event!(new_stop_dispenser, StopDispenser);
    new_control_event!(new_error, Error, Error);
    new_control_event!(new_other, Other);

    pub fn set_kind(mut self, kind: EventKind) -> Self {
        self.kind = kind;
        self
    }
    pub fn set_ctx<F>(mut self, f: F) -> Self
    where
        F: FnOnce(&mut Context),
    {
        f(&mut self.context);
        self
    }
    pub fn push_http_router(mut self, rhi: HttpRouterOpt) -> Self {
        if Operation::None == self.opt {
            self.opt = Operation::Router(RouterOps::Http(vec![rhi]));
        } else if let Operation::Router(ref mut rt) = self.opt {
            if let RouterOps::Http(ref mut rh) = rt {
                rh.push(rhi);
            }
        }
        self
    }
}

impl Default for ControlEvent {
    fn default() -> Self {
        let kind = EventKind::Other;
        let context = Context::new();
        let ops = Operation::None;
        Self {
            kind,
            context,
            opt: ops,
        }
    }
}

pub enum EventKind {
    BuildEP(EntryPoint), //新建一个EntryPoint服务
    RemoveEP(String),    //删除一个EntryPoint服务
    Operation(String),   //向某个EntryPoint的ctl发出指令
    StopDispenser,       //当前事件发生器停止运行,不需要继续监听
    Error(Error),        //发生了一个未知错误
    Other,               //未知的事件类型
}
impl Display for EventKind {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            EventKind::BuildEP(ep) => write!(
                f,
                "build entry point [{}]",
                to_string(ep).unwrap_or_else(|e| e.to_string())
            ),
            EventKind::RemoveEP(name) => write!(f, "remove entry point [{}]", name),
            EventKind::Operation(name) => write!(f, "operation entry point [{}]", name),
            EventKind::StopDispenser => write!(f, "stop this"),
            EventKind::Error(e) => write!(f, "error event:{}", e.to_string()),
            _ => write!(f, "unknown event"),
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum Operation {
    Router(RouterOps),
    Ip(Vec<IpOps>),
    None,
}

pub type OptResponse = wd_run::Context;

#[derive(Clone, Debug, PartialEq)]
pub enum RouterOps {
    Http(Vec<HttpRouterOpt>),
    Grpc,
    WebSocket,
    None,
}

#[derive(Clone, Debug, Default, PartialEq, ChainSet)]
pub struct HttpRouterOpt {
    pub opt_ty: HttpRouterOptTy,
    pub host: String,
    pub namespaces: String,
    pub path: String,
    pub target_host: String,
    pub target_port: u16,
}

#[derive(Clone, Debug, PartialEq, ChainSet)]
pub enum HttpRouterOptTy {
    Save,
    Delete,
}
impl Default for HttpRouterOptTy {
    fn default() -> Self {
        HttpRouterOptTy::Save
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum IpOps {
    AddBlack(Vec<String>),
    DeleteBlack(Vec<String>),
    AddWhite(Vec<String>),
    DeleteWhite(Vec<String>),
}
